<?php

require "ripcord-1.1/ripcord.php";

class subtitle {

    private $config;
    private $files;
    private $log;
    private $found_file = NULL;
    private $found_file_size = NULL;
    private $valid_ext = array("mkv", "avi", "mp4", "mpeg", "mpeg1", "mpeg2");

    public function __construct($config, $log) {
        $this->config = $config;
        if (!class_exists("files"))
            require "functions/files.php";
        $this->files = new files($config);
        $this->log = $log;
    }

    public function decompress_first_file_from_zip($ZIPContentStr) {
        if (strlen($ZIPContentStr) < 102) {
            //printf("error: input data too short<br />\n");
            return false;
        }
        $CompressedSize = $this->binstrtonum(substr($ZIPContentStr, 18, 4));
        $UncompressedSize = $this->binstrtonum(substr($ZIPContentStr, 22, 4));
        $FileNameLen = $this->binstrtonum(substr($ZIPContentStr, 26, 2));
        $ExtraFieldLen = $this->binstrtonum(substr($ZIPContentStr, 28, 2));
        $Offs = 30 + $FileNameLen + $ExtraFieldLen;
        $ZIPData = substr($ZIPContentStr, $Offs, $CompressedSize);
        $Data = gzinflate($ZIPData);
        if (strlen($Data) != $UncompressedSize) {
            //printf("error: uncompressed data have wrong size<br />\n");
            return false;
        }
        else
            return $Data;
    }

    public function binstrtonum($Str) {
        $Num = 0;
        for ($TC1 = strlen($Str) - 1; $TC1 >= 0; $TC1--) { //go from most significant byte
            $Num<<=8; //shift to left by one byte (8 bits)
            $Num|=ord($Str[$TC1]); //add new byte
        }
        return $Num;
    }

    public function opensubtitle_api($title = false, $language = array("eng"), $size = false, $imdbid = false, $moviehash = false) {
        $matched = preg_match('/(19|20)\d{2}\b/i', $title, $match);
        if ($matched) {
            $year = $match[0];
            $title = trim(str_replace("({$year})", "", $title));
        }
        $this->log->addmessage("Ripcord client load!");
        $client = ripcord::client('http://api.opensubtitles.org/xml-rpc');
        if (!$client) {
            $this->log->addmessage("Ripcord client failed!");
            return false;
        }
        $token_from_login = $client->LogIn('', '', "eng", 'autosorter');
        if ($token_from_login["status"] == false || $token_from_login["status"] == "401 Unauthorized") {
            $this->log->addmessage("Ripcord client denied!");
            return false;
        }
        if ($title)
            $query['query'] = $title;
        if ($size || $moviehash) {
            $query['moviebytesize'] = $size;
            $query['moviehash'] = $moviehash;
        }
        if ($imdbid)
            $query['imdbid'] = $imdbid;
        if ($year)
            $query['MovieYear'] = $year;

        foreach ($language as $lan) {
            $query['sublanguageid'] = $lan;
            $this->log->addmessage("Ripcord search for subtitle {$query['query']} [{$query['sublanguageid']}]!");
            $osget = $client->SearchSubtitles($token_from_login["token"], array($query));
            //array SearchSubtitles( $token, array(array('sublanguageid' => $sublanguageid, 'moviehash' => $moviehash, 'moviebytesize' => $moviesize, imdbid => $imdbid, query => 'movie name', "season" => 'season number', "episode" => 'episode number', 'tag' => tag ),array(...)))
            $this->log->addmessage("Ripcord search finished!");
            if ($osget["status"] == "401 Unauthorized") {
                $this->log->addmessage("Ripcord 401 unauth!");
                return false;
            }
            $bestmatch = false;
            foreach ($osget["data"] as $sub) {
                if ($sub["MovieYear"] != $year) {
                    //$this->log->addmessage("Ripcord search year mismatch!");
                    continue;
                }
                if ($size && (int) $sub["MovieByteSize"] == $size && $sub["SubLanguageID"] == $lan)
                    $bestmatch = $sub["ZipDownloadLink"];
            }
            if (!$bestmatch)
                foreach ($osget["data"] as $sub) {
                    if ($sub["MovieYear"] != $year) {
                        //$this->log->addmessage("Ripcord search year mismatch!");
                        continue;
                    }
                    if ($sub["SubLanguageID"] == $lan)
                        $bestmatch = $sub["ZipDownloadLink"];
                }
            $submatch[$lan] = $bestmatch;
        }
        $this->log->addmessage("Ripcord search matched!");
        return $submatch;
    }

    public function titlovi_api($title, $language) {
        
    }

    public function titlovi($title, $language) {
        $title = trim(substr($title, 0, strlen($title) - 6));
        foreach ($language as $lan) {
            if ($lan == "sr")
                $lan = "srpski";
            $url = "http://titlovi.com/titlovi/titlovi.aspx?prijevod={$title}&jezik={$lan}";
            $ctx = stream_context_create(array(
                'http' => array(
                    'timeout' => 3
                )
                    )
            );
            $page = file_get_contents($url, false, $ctx);
            if (!$page)
                return false;
            $dom = new DOMDocument();
            $dom->loadHTML($page);
            foreach ($dom->getElementsByTagName('span') as $node) {
                $node_html = $dom->saveHTML($node);
                $node_strip = strip_tags($node_html);
                if (strstr($node_html, 'span class="download"')) {
                    //"<span class="download"><a class="button" href="http://titlovi.com/titlovi/braveheart-149278/"><span>Skinite titl <em>(1707)</em></span></a></span>"
                    $p = preg_match('/titlovi\/[a-z,0-9,-]+\/"><span>\b/i', $node_html, $match);
                    if ($p) {
                        $match = explode("/", $match[0]);
                        $url1 = "http://titlovi.com/titlovi/{$match[1]}/";
                        $page1 = file_get_contents($url1, false, $ctx);
                    }
                }
            }
        }
        return $eps;
    }

    private function save_subtitle($directory, $title, $sl, $lang) {
        $path = $directory . "/" . $this->found_file;
        $fh = @fopen($sl, "r");
        if (!$fh)
            return false;
        $content = "";
        while (!feof($fh)) {
            $buffer = @fread($fh, 16384);
            $content.=$buffer;
        }
        @fclose($fh);
        if (empty($content) || $content[0] != "P" || $content[1] != "K")    // Header is not PKZIP?
            return false;
        $unzipped = $this->decompress_first_file_from_zip($content);
        if ($unzipped)
            @file_put_contents($path . ".{$lang}.srt", $unzipped);    // save
        return true;
    }

    public function download_subtitle($title, $directory, $size = false) {
        if (!$this->config["Subtitle"]["download_subtitles"])
            return false;
        $languages = $this->config["Subtitle"]["language"];
        $this->log->addmessage("Getting subtitle for {$title} from Opensubtitle");
        $sub = $this->opensubtitle_api($title, $languages, $size);
        if (empty($sub)) {
            $this->log->addmessage("Getting subtitle for {$title} failed!");
        } else {
            foreach ($sub as $lang => $sl) {
                if ($sl) {
                    $r = $this->save_subtitle($directory, $title, $sl, $lang);
                    if ($r)
                        $this->log->addmessage("Saved subtitle for {$title}");
                    else
                        $this->log->addmessage("Save failed for {$title}");
                }
            }   // foreach
        }   // else
    }

    public function find_subtitle($dir, $base) {
        foreach ($dir as $item) {
            $name = $item["name"];
            $ext = $this->files->extract_extension($name);
            if (in_array($ext, $this->valid_ext)) {         // find and extract just a name without extension
                $p = strpos($name, ".", strlen($name) - 5);     // no more than 5 last chars with . is extension
                if (!$p)
                    return false;
                $clean_name = substr($name, 0, $p);
                $this->found_file = $clean_name;
                $this->found_file_size = filesize($base . "/" . $name);
            }
            if (strstr(strtolower($name), ".srt") || strstr(strtolower($name), ".sub"))
                return true;
        }
        return false;
    }

    public function find_subtitles() {
        $subenabled = $this->config["Subtitle"]["download_subtitles"];
        if (!$subenabled)
            return false;
        $this->log->addmessage("Searching for missing subtitles");
        $dest = $this->config["Directories"]["destination"];
        $directories = $this->files->get_folder($dest);
        foreach ($directories as $dir) {
            $name = $dir["name"];
            $directories2 = $this->files->get_folder($dest . "/" . $name);
            $sub_exist = $this->find_subtitle($directories2, $dest . "/" . $name);
            if ($sub_exist)
                continue;
            $this->log->addmessage("Trying to download subtitle for {$name}");
            $this->download_subtitle($name, $dest . "/" . $name, $this->found_file_size);
        }
    }

}

?>
